if (query) {
if (multicast < 0)
- multicast = interface_multicast(iface);
+ multicast = iface->need_multicast;
for (i = 0; i < pkt_n_q; i++)
dns_question_set_multicast(pkt_q[i], multicast);
interface_start(if_new);
}
-static int interface_init_socket(enum umdns_socket_type type)
+static int interface_init_socket(enum umdns_socket_type type, bool *mcast)
{
struct sockaddr_in6 local6 = {
.sin6_family = AF_INET6
int no = 0;
int fd;
int af = (type & SOCKTYPE_BIT_IPV6) ? AF_INET6 : AF_INET;
+ bool reuseport = false;
if (ufd[type].fd >= 0)
return 0;
return -1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
-#ifdef SO_REUSEPORT
- setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
-#endif
switch (type) {
case SOCK_UC_IPV4:
break;
}
+retry:
if (type & SOCKTYPE_BIT_IPV6) {
ufd[type].cb = read_socket6;
if (bind(fd, (struct sockaddr *)&local6, sizeof(local6)) < 0)
return 0;
error:
+ if (!reuseport) {
+#ifdef SO_REUSEPORT
+ setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
+#endif
+ reuseport = true;
+ *mcast = true;
+ goto retry;
+ }
close(ufd[type].fd);
return -1;
}
{
struct interface *iface;
unsigned int ifindex;
+ bool mcast = false;
char *id_buf;
- if (interface_init_socket(type))
+ if (interface_init_socket(type, &mcast))
goto error;
ifindex = if_nametoindex(name);
iface->ifindex = ifindex;
iface->type = type;
iface->addrs = *list;
+ iface->need_multicast = mcast;
vlist_add(&interfaces, &iface->node, id_buf);
return;